package com.wang.config;

import com.wang.pojo.Configuration;
import com.wang.pojo.MappedStatement;
import com.wang.sqlsession.SqlCommandType;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by wangq on 2021/6/29.
 *
 * 解析sql映射文件
 */
public class XMLMapperBuilder {
    private Configuration configuration;

    public XMLMapperBuilder(Configuration configuration) {
        this.configuration = configuration;
    }

    /**
     * 解析sql映射文件
     *
     * @param inputStream sql映射文件字节流
     * @throws DocumentException
     */
    public void parseMapper(InputStream inputStream) throws DocumentException {
        Document document = new SAXReader().read(inputStream);
        Element rootElement = document.getRootElement();
        String nameSpace = rootElement.attributeValue("namespace");

        // 获取mapper节点下的所有子节点全限定名
        List<String> allSqlCommandTypeList = new ArrayList<>();
        List<Element> mapperElementList = rootElement.selectNodes("//mapper");
        for (Element element : mapperElementList) {
            List<Element> mapperChildElementList = element.elements();
            for (Element mapperChildElement : mapperChildElementList) {
                String qualifiedName = mapperChildElement.getQualifiedName();
                if (!allSqlCommandTypeList.contains(qualifiedName)) {
                    allSqlCommandTypeList.add(qualifiedName);
                    System.out.println(qualifiedName);
                }
            }
        }

        // 把所有操作类型的sql都解析出来
        for (String sqlCommandTypeStr : allSqlCommandTypeList) {
            // 获取映射sql文件的所有select节点 ，并遍历拿出每个节点的信息 封装到MappedStatement中
            List<Element> selectElementList = rootElement.selectNodes("//" + sqlCommandTypeStr);
            for (Element selectElement : selectElementList) {
                String id = selectElement.attributeValue("id");
                String resultType = selectElement.attributeValue("resultType");
                String parameterType = selectElement.attributeValue("parameterType");
                String sqlText = selectElement.getTextTrim();
                SqlCommandType sqlCommandType = SqlCommandType.convertToType(selectElement.getQualifiedName());

                MappedStatement mappedStatement = new MappedStatement();
                mappedStatement.setId(id);
                mappedStatement.setResultType(resultType);
                mappedStatement.setParameterType(parameterType);
                mappedStatement.setSql(sqlText);
                mappedStatement.setSqlCommandType(sqlCommandType);
                // 使用sql映射文件的nameSpace和sql语句id作为mappedStatementKey
                String mappedStatementKey = nameSpace + "." + id;
                // 把封装好的每个MappedStatement存入Configuration中
                configuration.getMappedStatementMap().put(mappedStatementKey, mappedStatement);
            }
        }
    }
}
